package service

import (
	"context"
	"time"
	"wx-uniapp-go/internal/domain/errcode"
	"wx-uniapp-go/internal/repository/dto"
	"wx-uniapp-go/internal/repository/models"
)

// SignInService 签到服务接口
type SignInService interface {
	// SignIn 签到
	SignIn(ctx context.Context, userId int64) (*dto.SignInResp, error)

	// GetSignInStatus 获取签到状态
	GetSignInStatus(ctx context.Context, userId int64) (*dto.SignInStatusResp, error)

	// ListSignInRecords 获取签到记录列表
	ListSignInRecords(ctx context.Context, userId int64, req *dto.ListSignInRecordReq) (*dto.ListSignInRecordResp, error)
}

// signInService 签到服务实现
type signInService struct {
}

// NewSignInService 创建签到服务实例
func NewSignInService() SignInService {
	return &signInService{}
}

// SignIn 签到
func (s *signInService) SignIn(ctx context.Context, userId int64) (*dto.SignInResp, error) {
	// 检查今日是否已签到
	todayRecord, err := models.GetTodaySignIn(ctx, userId)
	if err != nil {
		return nil, err
	}
	if todayRecord != nil {
		return nil, errcode.SignInAlreadyDone
	}

	// 获取最后一次签到记录
	lastRecord, err := models.GetLastSignIn(ctx, userId)
	if err != nil {
		return nil, err
	}

	// 计算连续签到天数
	continuousDays := 1
	if lastRecord != nil {
		lastSignDate := lastRecord.SignDate
		today := time.Now()
		// 如果最后签到日期是昨天,连续签到天数+1
		if lastSignDate.AddDate(0, 0, 1).Format("2006-01-02") == today.Format("2006-01-02") {
			continuousDays = lastRecord.ContinuousDays + 1
		}
	}

	// 获取签到规则
	rule, err := models.GetSignInRule(ctx, continuousDays)
	if err != nil {
		return nil, err
	}
	if rule == nil {
		return nil, errcode.SignInRuleNotExist
	}

	// 计算红包金额
	redPacketAmount := rule.CalculateRedPacketAmount()

	// 创建签到记录
	record := &models.SignInRecord{
		UserId:          userId,
		SignDate:        time.Now(),
		ContinuousDays:  continuousDays,
		RedPacketAmount: redPacketAmount,
	}

	if err := models.CreateSignInRecord(ctx, record); err != nil {
		return nil, err
	}

	return &dto.SignInResp{
		RedPacketAmount: redPacketAmount,
		ContinuousDays:  continuousDays,
	}, nil
}

// GetSignInStatus 获取签到状态
func (s *signInService) GetSignInStatus(ctx context.Context, userId int64) (*dto.SignInStatusResp, error) {
	// 获取今日签到记录
	todayRecord, err := models.GetTodaySignIn(ctx, userId)
	if err != nil {
		return nil, err
	}

	// 获取最后一次签到记录
	lastRecord, err := models.GetLastSignIn(ctx, userId)
	if err != nil {
		return nil, err
	}

	// 计算连续签到天数
	continuousDays := 0
	var lastSignInDate time.Time
	if lastRecord != nil {
		lastSignInDate = lastRecord.SignDate
		if todayRecord != nil {
			continuousDays = todayRecord.ContinuousDays
		} else {
			// 如果最后签到日期是昨天,连续签到天数+1
			today := time.Now()
			if lastSignInDate.AddDate(0, 0, 1).Format("2006-01-02") == today.Format("2006-01-02") {
				continuousDays = lastRecord.ContinuousDays + 1
			} else {
				continuousDays = 1
			}
		}
	}

	// 获取今日签到规则
	rule, err := models.GetSignInRule(ctx, continuousDays)
	if err != nil {
		return nil, err
	}

	var ruleInfo *dto.SignInRuleInfo
	if rule != nil {
		ruleInfo = &dto.SignInRuleInfo{
			MinAmount:      rule.MinAmount,
			MaxAmount:      rule.MaxAmount,
			ExtraAmount:    rule.ExtraAmount,
			ContinuousDays: rule.ContinuousDays,
		}
	}

	return &dto.SignInStatusResp{
		HasSignedToday: todayRecord != nil,
		ContinuousDays: continuousDays,
		LastSignInDate: lastSignInDate,
		TodayRule:      ruleInfo,
	}, nil
}

// ListSignInRecords 获取签到记录列表
func (s *signInService) ListSignInRecords(ctx context.Context, userId int64, req *dto.ListSignInRecordReq) (*dto.ListSignInRecordResp, error) {
	var records []*models.SignInRecord
	total, err := models.FindByPage(ctx, &records, req.Page, req.PageSize, "user_id = ?", userId)
	if err != nil {
		return nil, err
	}

	list := make([]dto.SignInRecordItem, 0, len(records))
	for _, record := range records {
		list = append(list, dto.SignInRecordItem{
			Id:              record.Id,
			SignDate:        record.SignDate,
			ContinuousDays:  record.ContinuousDays,
			RedPacketAmount: record.RedPacketAmount,
			CreateTime:      record.CreateTime,
		})
	}

	return &dto.ListSignInRecordResp{
		Total:    total,
		List:     list,
		Page:     req.Page,
		PageSize: req.PageSize,
	}, nil
}
